﻿using wwl.Contract.Dtos.Common;
using wwl.Contract.Dtos.Requests.Rbac;
using wwl.Contract.Dtos.Responses.Rbac;

namespace wwl.Contract.Interfaces.Rbac
{
  /// <summary>
  /// 租户领域服务接口（DDD 应用层与领域层的交互契约）
  /// 定义租户相关的核心业务操作规范，封装租户领域的完整业务流程与规则校验
  /// 属于权限模块（Rbac）的核心服务接口，是前端/外部系统调用租户业务能力的入口
  /// </summary>
  /// <remarks>
  /// DDD 设计定位：领域服务接口位于契约层，定义“做什么”，不关注“怎么做”（实现位于应用层）
  /// 职责边界：协调领域实体（<see cref="wwl.Domain.Entities.Rbac.Tenant"/>）与仓储（<see cref="ITenantRepository"/>），
  /// 封装跨实体/聚合的业务流程，不包含数据访问细节或前端交互逻辑
  /// </remarks>
  public interface ITenantService
  {
    /// <summary>
    /// 异步根据ID查询租户详情（领域查询操作）
    /// </summary>
    /// <param name="id">租户唯一标识（对应领域实体<see cref="wwl.Domain.Entities.Rbac.Tenant.Id"/>）</param>
    /// <returns>
    /// 找到则返回租户DTO（<see cref="TenantResponse"/>），未找到则返回null
    /// DTO包含租户的核心业务字段（如编码、名称、状态），适配前端展示需求
    /// </returns>
    /// <remarks>
    /// 业务规则：仅返回未逻辑删除的租户（IsDeleted=false），符合领域层“无效状态数据不暴露”的原则
    /// </remarks>
    Task<TenantResponse?> GetByIdAsync(string id);

    /// <summary>
    /// 异步创建租户（领域命令操作）
    /// </summary>
    /// <param name="request">创建租户的请求参数（包含租户编码、名称等核心业务字段）</param>
    /// <param name="createdBy">创建人标识（如用户ID，用于审计追踪）</param>
    /// <returns>创建成功后的租户DTO（包含自动生成的ID、创建时间等完整信息）</returns>
    /// <remarks>
    /// 封装完整创建流程（DDD 领域流程协调）：
    /// 1. 校验请求参数合法性（如编码非空、名称长度限制）；
    /// 2. 校验租户编码唯一性（调用<see cref="ITenantRepository.ExistsByCodeAsync"/>）；
    /// 3. 构建领域实体（<see cref="wwl.Domain.Entities.Rbac.Tenant"/>）并设置初始状态；
    /// 4. 调用仓储保存实体，返回映射后的DTO。
    /// 所有业务规则在此流程中统一执行，确保领域状态一致性
    /// </remarks>
    Task<TenantResponse> CreateAsync(CreateTenantRequest request, string createdBy);

    /// <summary>
    /// 异步更新租户信息（领域命令操作）
    /// </summary>
    /// <param name="id">待更新租户的唯一标识</param>
    /// <param name="request">更新租户的请求参数（如名称、状态等可修改字段）</param>
    /// <returns>更新后的租户DTO（反映最新状态）</returns>
    /// <remarks>
    /// 业务流程与规则：
    /// 1. 校验租户是否存在（不存在则抛异常）；
    /// 2. 若更新编码，需校验新编码的唯一性（排除自身ID）；
    /// 3. 调用领域实体的状态变更方法（如<see cref="wwl.Domain.Entities.Rbac.Tenant.Enable"/>）；
    /// 4. 同步更新实体的<see cref="wwl.Domain.Entities.Common.BaseEntity.UpdatedTime"/>；
    /// 体现 DDD“领域实体自包含状态变更逻辑”，服务仅负责协调流程
    /// </remarks>
    Task<TenantResponse> UpdateAsync(string id, UpdateTenantRequest request);

    /// <summary>
    /// 异步删除租户（领域命令操作，默认执行逻辑删除）
    /// </summary>
    /// <param name="id">待删除租户的唯一标识</param>
    /// <returns>删除成功返回true；租户不存在返回false</returns>
    /// <remarks>
    /// 业务规则：
    /// 1. 执行逻辑删除（设置<see cref="wwl.Domain.Entities.Common.BaseEntity.IsDeleted"/>=true），保留历史数据；
    /// 2. 若租户存在关联数据（如用户、角色），可能抛出业务异常（取决于领域规则）；
    /// 符合 DDD“删除是业务操作，而非单纯技术操作”的思想
    /// </remarks>
    Task<bool> DeleteAsync(string id);

    /// <summary>
    /// 异步执行租户分页查询（领域查询操作）
    /// </summary>
    /// <param name="request">租户分页查询请求（包含页码、页大小及租户特有筛选条件）</param>
    /// <returns>
    /// 分页结果DTO（<see cref="PagedResult{TenantDto}"/>），包含：
    /// - Total：符合条件的租户总条数；
    /// - Items：当前页的租户DTO列表（适配前端表格展示）。
    /// </returns>
    /// <remarks>
    /// 与仓储分页的区别：
    /// 1. 仓储返回领域实体（<see cref="wwl.Domain.Entities.Rbac.Tenant"/>），本方法返回DTO，隔离领域与外部；
    /// 2. 可在此层附加跨领域的筛选逻辑（如结合当前用户权限过滤可见租户），体现应用层的协调能力。
    /// </remarks>
    Task<PagedResult<TenantResponse>> GetPagedAsync(TenantPagedRequest request);
  }
}